﻿using System.IO;
using System.Security.Principal;
using System.Web;
using EditRegion.MVC.Repository;
using EditRegion.MVC.Repository.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Web.Mvc;
using Moq;

namespace EditRegion.MVC.Tests
{
    [TestClass()]
    public class EditRegionMarkUpTest
    {
        #region TestContext
        private TestContext testContextInstance;

        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        } 
        #endregion

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestMethod()]
        public void ToStringTest()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "";
            string actual = target.ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Valid_Region_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "Region1";
            string actual = target.GetEditRegion("Region1").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_InValid_Region_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            string expected = string.Empty;
            string actual = target.GetEditRegion("Invalid").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Label_And_Valid_RegionId_And_Valid_User_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = @"<label for=""Region1"">Region1 Label</label><textarea id='Region1' name='Region1'>Region1</textarea><ul class='editRegionSave'><li><a id=""save"" href='#' onclick=""saveEditRegion('Region1');"" >save</a><li id=""result_Region1""></li></ul>";
            string actual = target.GetEditRegion("Region1").Label("Region1 Label").EditableForUser("Administrator").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_Valid_User_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = @"<textarea id='Region1' name='Region1'>Region1</textarea><ul class='editRegionSave'><li><a id=""save"" href='#' onclick=""saveEditRegion('Region1');"" >save</a><li id=""result_Region1""></li></ul>";
            string actual = target.GetEditRegion("Region1").EditableForUser("Administrator").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_InValid_User_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "Region1";
            string actual = target.GetEditRegion("Region1").EditableForUser("InvalidUser").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_Valid_Users_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = @"<textarea id='Region1' name='Region1'>Region1</textarea><ul class='editRegionSave'><li><a id=""save"" href='#' onclick=""saveEditRegion('Region1');"" >save</a><li id=""result_Region1""></li></ul>";
            string actual = target.GetEditRegion("Region1").EditableForUsers(new[] {"Administrator"}).ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_InValid_Users_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "Region1";
            string actual = target.GetEditRegion("Region1").EditableForUsers(new[] { "Invalid" }).ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_Valid_Role_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = @"<textarea id='Region1' name='Region1'>Region1</textarea><ul class='editRegionSave'><li><a id=""save"" href='#' onclick=""saveEditRegion('Region1');"" >save</a><li id=""result_Region1""></li></ul>";
            string actual = target.GetEditRegion("Region1").EditableForRole("Administrators").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_InValid_Role_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "Region1";
            string actual = target.GetEditRegion("Region1").EditableForRole("InvalidRole").ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_Valid_Roles_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = @"<textarea id='Region1' name='Region1'>Region1</textarea><ul class='editRegionSave'><li><a id=""save"" href='#' onclick=""saveEditRegion('Region1');"" >save</a><li id=""result_Region1""></li></ul>";
            string actual = target.GetEditRegion("Region1").EditableForRoles(new[] { "Administrators" }).ToString();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void Get_Editable_Region_With_Valid_RegionId_And_InValid_Roles_Test()
        {
            EditRegionMarkUp target = GetEditRegionMarkUpInstance();
            const string expected = "Region1";
            string actual = target.GetEditRegion("Region1").EditableForRoles(new[] { "Invalid" }).ToString();
            Assert.AreEqual(expected, actual);
        }

        #region Helper Methods
        private static EditRegionMarkUp GetEditRegionMarkUpInstance()
        {
            HtmlHelper htmlHelper = GetHtmlHelperInstance();
            FileInfo fileInfo = GetContentFileInfo();
            IPrincipal user = GetUser();
            EditRegionMarkUp editRegionMarkUp = new EditRegionMarkUp(htmlHelper, fileInfo, user);
            return editRegionMarkUp;
        }

        private static FileInfo GetContentFileInfo()
        {
            if (File.Exists("Content.xml")) { File.Delete("Content.xml"); }
            FileInfo fileInfo = new FileInfo(@"Content.xml");
            IContentRepository target = new XmlRepository(fileInfo);
            target.Add("Region1", "Region1");
            target.Add("Region2", "Region2");
            target.Add("Region3", "Region3");
            return fileInfo;
        }

        private static IPrincipal GetUser()
        {
            IPrincipal fakeUser = new GenericPrincipal(new GenericIdentity("Administrator", "Forms"), null);

            var httpContext = new Mock<HttpContextBase>();
            var principal = new Mock<IPrincipal>();

            httpContext.SetupGet(c => c.User).Returns(principal.Object);
            principal.Setup(p => p.IsInRole("Administrators")).Returns(true);
            principal.Setup(p => p.Identity).Returns(fakeUser.Identity);
            
            return principal.Object;
        }

        private static HtmlHelper GetHtmlHelperInstance()
        {
            ViewContext viewContext = new Mock<ViewContext>().Object;
            HtmlHelper htmlHelper = new HtmlHelper(viewContext, new Mock<IViewDataContainer>().Object);
            return htmlHelper;
        }
        #endregion
    }
}
